import { PureComponent } from 'react';
import {
  Scene, OrthographicCamera, BoxGeometry, Line, Vector3,
  Mesh, WebGLRenderer, DirectionalLight,
  MeshBasicMaterial, DoubleSide
} from 'three';
import Stats from 'stats.js';
import OBJLoader from '@/utils/OBJLoader';
import { requestAnimationFrame } from '@/utils/requestAnimationFrame';

const drawAxes = scene => {
  const xGeo = new BoxGeometry();
  const xGeoPoints = [
    new Vector3(0, 0, 0),
    new Vector3(6, 0, 0)
  ];
  xGeo.setFromPoints(xGeoPoints);
  const xMat = new MeshBasicMaterial({
    color: 0xff0000
  });
  const xAxis = new Line(xGeo, xMat);
  scene.add(xAxis);

  const yGeo = new BoxGeometry();
  const yGeoPoints = [
    new Vector3(0, 0, 0),
    new Vector3(0, 6, 0)
  ];
  yGeo.setFromPoints(yGeoPoints);
  const yMat = new MeshBasicMaterial({
    color: 0x00ff00
  });
  const yAxis = new Line(yGeo, yMat);
  scene.add(yAxis);

  const zGeo = new BoxGeometry();
  const zGeoPoints = [
    new Vector3(0, 0, 0),
    new Vector3(0, 0, 6)
  ];
  zGeo.setFromPoints(zGeoPoints);
  const zMat = new MeshBasicMaterial({
    color: 0x00ccff
  });
  const zAxis = new Line(zGeo, zMat);
  scene.add(zAxis);
};

const scene = new Scene();

drawAxes(scene);

const camera = new OrthographicCamera(-5, 5, 3.75, -3.75, 0.1, 100);
camera.position.set(15, 25, 25);
camera.lookAt(0, 2, 0);

//光照会影响物体材质的颜色
const light = new DirectionalLight(0xffffff);
light.position.set(20, 10, 5);
scene.add(light);

let renderer = null;

let mesh = null;

let animateId = 0;

const stats = new Stats();

const animate = () => {
  stats.begin();

  //旋转一周(2π)之后会回到原点,
  //此时之后的运动就都是之前运动的重复
  //因此可以在一周之后做一个重置的操作, 妙啊
  mesh.rotation.y += 0.01;
  if(mesh.rotation.y > Math.PI * 2) {
    mesh.rotation.y -= Math.PI * 2;
  }

  renderer.render(scene, camera);
  stats.end();
  animateId = requestAnimationFrame(animate);
};

const startAnimate = () => {
  if(animateId) return;
  animateId = requestAnimationFrame(animate);
};

const stopAnimate = () => {
  if(!animateId) return;
  cancelAnimationFrame(animateId);
  animateId = 0;
};

class Index extends PureComponent {

  componentDidMount() {
    renderer = new WebGLRenderer({
      canvas: document.getElementById('mainCanvas')
    });
    renderer.render(scene, camera);

    const fpsContainer = document.getElementById('fps-container');
    stats.domElement.style.position = '';
    fpsContainer.appendChild(stats.dom);

    const objLoader = new OBJLoader();
    objLoader.load('/models/port.obj', obj => {
      //loader将3d max模型转换成threejs能识别内容之后就能给threejs使用了
      //但此时能观察到渲染不完整的情况, 就是只有正面被绘制, 于是便有了法二
      //法一
      // mesh = obj;
      // scene.add(mesh);
      // renderer.render(scene, camera);

      //法二: 双面绘制
      obj.traverse(child => {
        if(child instanceof Mesh) {
          //不做处理, 也就是法一, 这个地方默认值是0, 也就是FrontSide正面
          //这里也可以设置为2, 因为DoubleSide是threejs定义的一个常量
          //它的值就是2, 但使用变量的话语义更明确一些
          child.material.side = DoubleSide;
        }
      });

      mesh = obj;
      scene.add(mesh);
      renderer.render(scene, camera);
    });

  }

  render() {

    return (
      <div>
        <div>
          <button
            onClick={startAnimate}
          >开始</button>
          <button
            onClick={stopAnimate}
          >停止</button>
        </div>
        <div
          id="fps-container"
          style={{
            display: 'flex',
            padding: '5px'
          }}
        />
        <canvas
          id="mainCanvas"
          width="400"
          height="300"
        />
      </div>
    );
  }
}

export default Index;